package com.heima.comment.Service.impl;

import com.alibaba.fastjson.JSON;
import com.heima.common.constants.HotArticleConstants;
import com.heima.common.constants.WemediaConstants;
import com.heima.common.redis.CacheService;
import com.heima.feign.article.IArticleClient;
import com.heima.feign.user.IUserClient;
import com.heima.feign.wemedia.IWemediaClient;
import com.heima.model.comment.dtos.RepayCommentDto;
import com.heima.comment.service.CommentService;
import com.heima.model.comment.dtos.*;
import com.heima.model.comment.pojos.ApComment;
import com.heima.model.comment.pojos.ApCommentLike;
import com.heima.model.comment.pojos.ApCommentRepay;
import com.heima.model.comment.pojos.ApCommentRepayLike;
import com.heima.model.comment.vo.CommentVo;
import com.heima.model.comment.vo.RepayCommentVo;
import com.heima.model.common.dtos.ResponseResult;
import com.heima.model.common.enums.AppHttpCodeEnum;
import com.heima.model.mess.UpdateArticleMess;
import com.heima.model.user.pojos.ApUser;
import com.heima.model.wemedia.pojos.WmSensitive;
import com.heima.utils.common.SensitiveWordUtil;
import com.heima.utils.thread.ApUserThreadLocalUtil;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.BeanUtils;
import org.apache.commons.lang.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.domain.Sort;
import org.springframework.data.mongodb.core.MongoTemplate;
import org.springframework.data.mongodb.core.query.Criteria;
import org.springframework.data.mongodb.core.query.Query;
import org.springframework.data.mongodb.core.query.Update;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.kafka.core.KafkaTemplate;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.util.*;
import java.util.stream.Collectors;

@Service
@Transactional
@Slf4j
public class CommentServiceImpl implements CommentService {
    @Autowired
    private MongoTemplate mongoTemplate;
    @Autowired
    private CacheService cacheService;
    @Autowired
    private IUserClient iUserClient;
    @Autowired
    private com.heima.comment.service.impl.GreenScanServiceImpl greenScanService;
    @Autowired
    private IWemediaClient iWemediaClient;
    @Autowired
    private KafkaTemplate kafkaTemplate;

    @Autowired
    private IArticleClient iArticleClient;
    /**
     * @param dto
     * @Description: 回复评论
     * @Date 2023/6/28 11:09
     * @Author 朱传洋
     */
    @Override
    public ResponseResult replyComment(RepayCommentDto dto) {
        //1.非空校验
        if (dto==null|| StringUtils.isBlank(dto.getContent())){
            return ResponseResult.errorResult(AppHttpCodeEnum.PARAM_REQUIRE);
        }
        //判断用户是否登陆
        Integer userId = ApUserThreadLocalUtil.get();
        if (userId==null){
            return ResponseResult.errorResult(AppHttpCodeEnum.NEED_LOGIN);
        }
        //2.审核评论内容
        //2.1.自审核敏感词
        boolean isSensitive = handleSensitiveScan(dto.getContent());
        if(!isSensitive) return ResponseResult.errorResult(AppHttpCodeEnum.COMMENT_SCAN_FAIL);

        //2.2.百度审核评论
        boolean isTextScan = scanText(dto.getContent());
        if(!isTextScan) return ResponseResult.errorResult(AppHttpCodeEnum.COMMENT_SCAN_FAIL);

        //3.根据评论Id查询评论
        Query query = Query.query(Criteria.where("id").is(dto.getCommentId()));
        ApComment comment = mongoTemplate
                .findOne(query, ApComment.class);

        //4.判断评论是否存在
        if (comment==null){
            return ResponseResult.errorResult(AppHttpCodeEnum.AP_USER_DATA_NOT_EXIST,"评论不存在或者已被删除");
        }
        //5.封装回复评论数据
        ApCommentRepay replyComment=new ApCommentRepay();
        replyComment.setCommentId(dto.getCommentId());
        replyComment.setAuthorId(userId);
        //调用feign查询用户信息
        ApUser apUser = iUserClient.getApUser(userId);
        replyComment.setAuthorName(apUser.getName());
        replyComment.setContent(dto.getContent());
        replyComment.setCreatedTime(new Date());
        replyComment.setUpdatedTime(new Date());
        //6.保存到mongoDB
        mongoTemplate.save(replyComment);
        //7.修改评论表中的评论回复数量
        Update reply = Update.update("reply", comment.getReply() + 1);
        mongoTemplate.updateFirst(query,reply,ApComment.class);

        //8.发送消息更新article
        UpdateArticleMess mess = new UpdateArticleMess();
        mess.setArticleId(comment.getEntryId());
        mess.setAdd(1);
        mess.setType(UpdateArticleMess.UpdateArticleType.COMMENT);
        kafkaTemplate.send(HotArticleConstants.HOT_ARTICLE_SCORE_TOPIC, JSON.toJSONString(mess));
        return ResponseResult.okResult(AppHttpCodeEnum.SUCCESS);

    }

    /**
     * @Author: 丁伟伟
     * @Description: 评论--保存评论
     * @DateTime: 13:07 2023/6/28
     */
    @Override
    public ResponseResult saveByDing(CommentSaveDto dto) {
        //参数校验
        if(dto == null || dto.getArticleId() == null || dto.getContent() == null || dto.getContent().length() > 140)
            return ResponseResult.errorResult(AppHttpCodeEnum.PARAM_INVALID);

        //校验登录
        Integer userId = ApUserThreadLocalUtil.get();
        if(userId == null)
            return ResponseResult.errorResult(AppHttpCodeEnum.NEED_LOGIN);

        // 校验文章是否可以评论
        boolean comment = iArticleClient.comment(dto.getArticleId());
        if (comment == false)
            return ResponseResult.errorResult(AppHttpCodeEnum.PARAM_INVALID );

        //2.审核评论内容
        //2.1.自审核敏感词
        boolean isSensitive = handleSensitiveScan(dto.getContent());
        if(!isSensitive) return ResponseResult.errorResult(AppHttpCodeEnum.COMMENT_SCAN_FAIL);

        //2.2.百度审核评论
        boolean isTextScan = scanText(dto.getContent());
        if(!isTextScan) return ResponseResult.errorResult(AppHttpCodeEnum.COMMENT_SCAN_FAIL);

        //业务处理
        ApUser apUser = iUserClient.getApUser(userId);

        ApComment apComment = new ApComment();
        apComment.setAuthorId(userId);
        apComment.setContent(dto.getContent());
        apComment.setCreatedTime(new Date());
        apComment.setEntryId(dto.getArticleId());
        apComment.setAuthorName(apUser.getName());
        apComment.setLikes(0);
        apComment.setReply(0);
        apComment.setType((short) 0);
        apComment.setFlag((short) 0);

        mongoTemplate.save(apComment);

        //发送消息更新article
        UpdateArticleMess mess = new UpdateArticleMess();
        mess.setArticleId(dto.getArticleId());
        mess.setAdd(1);
        mess.setType(UpdateArticleMess.UpdateArticleType.COMMENT);
        kafkaTemplate.send(HotArticleConstants.HOT_ARTICLE_SCORE_TOPIC, JSON.toJSONString(mess));

        return ResponseResult.okResult(AppHttpCodeEnum.SUCCESS);
    }

    /**
     * @Author: 丁伟伟
     * @Description: 查询评论列表
     * @DateTime: 13:07 2023/6/28
     */
    @Override
    public ResponseResult loadByDing(CommentDto dto) {
        //参数校验
        if(dto == null || dto.getArticleId() == null || dto.getMinDate() == null)
            return ResponseResult.errorResult(AppHttpCodeEnum.PARAM_INVALID);

        //分页查询
        int size = 10;
        Query query = Query.query(Criteria.where("entryId").is(dto.getArticleId()).and("createdTime").lt(dto.getMinDate()));
        query.with(Sort.by(Sort.Direction.DESC, "createdTime")).limit(size);
        List<ApComment> list = mongoTemplate.find(query, ApComment.class);

        //获取operation字段：评论点赞表数据
        List<String> idList = list.stream().map(x -> x.getId()).collect(Collectors.toList());
        Query query1 = Query.query(Criteria.where("commentId").in(idList));
        List<ApCommentLike> apCommentLikes = mongoTemplate.find(query1, ApCommentLike.class);
        if (apCommentLikes == null) {
            return ResponseResult.okResult(list);
        }

        //封装数据返回
        List<CommentVo> commentVos = new ArrayList<>();
        for (ApComment apComment : list) {
            CommentVo commentVo = new CommentVo();
            BeanUtils.copyProperties(apComment,commentVo);

            for (ApCommentLike apCommentLike : apCommentLikes) {
                if(apCommentLike.getCommentId().equals(apComment.getId())){
                    commentVo.setOperation((short) 0);
                    break;
                }
            }
            commentVos.add(commentVo);
        }

        return ResponseResult.okResult(commentVos);
    }

    /**
     * @Author: 丁伟伟
     * @Description: 点赞评论
     * @DateTime: 13:07 2023/6/28
     */
    @Override
    public ResponseResult likeByDing(CommentLikeDto dto) {
        //参数校验
        if(dto == null || dto.getCommentId() == null || (dto.getOperation() != 0 && dto.getOperation() != 1))
            return ResponseResult.errorResult(AppHttpCodeEnum.PARAM_INVALID);

        //验证登录
        Integer userId = ApUserThreadLocalUtil.get();
        if(userId == null)
            return ResponseResult.errorResult(AppHttpCodeEnum.NEED_LOGIN);

        //点赞：ApCommentLike表添加数据；ApComment的likes加一
        ApComment comment = mongoTemplate.findById(dto.getCommentId(), ApComment.class);//评论

        if(dto.getOperation() == 0){
            ApCommentLike apCommentLike = new ApCommentLike();
            apCommentLike.setAuthorId(userId);
            apCommentLike.setCommentId(dto.getCommentId());
            mongoTemplate.save(apCommentLike);

            comment.setLikes(comment.getLikes() + 1);//默认为0
            mongoTemplate.save(comment);
        }else {
            //取消点赞：删除ApCommentLikes表数据，ApComment的likes减一
            Query query = Query.query(Criteria.where("commentId").is(comment.getId()).and("authorId").is(userId));
            if(query == null) return ResponseResult.errorResult(AppHttpCodeEnum.DATA_NOT_EXIST);
            mongoTemplate.remove(query,ApCommentLike.class);

            comment.setLikes(comment.getLikes() - 1);
            mongoTemplate.save(comment);
        }

        //封装结果返回
        Map<String, Object> result = new HashMap<>();
        result.put("likes", comment.getLikes());
        return ResponseResult.okResult(result);
    }

    /**
     * @param dto
     * @Description: 查询评论回复列表
     * @Date 2023/6/28 15:04
     * @Author 朱传洋
     */
    @Override
    public ResponseResult loadRepayComment(CommentRepayDto dto) {
        //1.非空校验
        if (dto==null){
            return ResponseResult.errorResult(AppHttpCodeEnum.PARAM_REQUIRE);
        }
        //2.数据处理
        if (dto.getSize()==null||dto.getSize()<=0||dto.getSize()>50){
            dto.setSize(10);
        }
        if (dto.getMinDate()==null) {
            dto.setMinDate(new Date());
        }
        Integer userId = ApUserThreadLocalUtil.get();
        if (userId==null){
            return ResponseResult.errorResult(AppHttpCodeEnum.NEED_LOGIN);
        }
        //3.根据评论id查询回复
        Query query = Query.query(Criteria.where("commentId").is(dto.getCommentId())
                .and("createdTime").lt(dto.getMinDate()))
                .with(Sort.by(Sort.Direction.DESC, "createdTime"))
                .limit(dto.getSize());
        List<ApCommentRepay> apCommentRepayList = mongoTemplate.find(query, ApCommentRepay.class);
        //4.返回数据
        List<RepayCommentVo> list=new ArrayList<>();

        for (ApCommentRepay apCommentRepay : apCommentRepayList) {
            RepayCommentVo repayCommentVo=new RepayCommentVo();
            BeanUtils.copyProperties(apCommentRepay,repayCommentVo);
            Query query1 = Query.query(Criteria.where("commentRepayId").is(apCommentRepay.getId()).and("authorId").is(userId));
            ApCommentRepayLike repayLike = mongoTemplate.findOne(query1, ApCommentRepayLike.class);
            if (repayLike==null){
                repayCommentVo.setOperation((short)1);
            }else {
                repayCommentVo.setOperation((short)0);
            }
            list.add(repayCommentVo);
        }
        return ResponseResult.okResult(list);
    }

    /**
     * @param dto
     * @Description: 点赞回复的评论
     * @Date 2023/6/28 15:09
     * @Author 朱传洋
     */
    @Override
    public ResponseResult likeRepayComment(CommentRepayLikeDto dto) {
        //1.非空校验
        if (dto==null){
            return ResponseResult.errorResult(AppHttpCodeEnum.PARAM_REQUIRE);
        }
        Integer userId = ApUserThreadLocalUtil.get();
        if (userId==null){
            return ResponseResult.errorResult(AppHttpCodeEnum.NEED_LOGIN);
        }
        //查询回复评论
        Query query = Query.query(Criteria.where("id").is(dto.getCommentRepayId()));
        ApCommentRepay commentRepay = mongoTemplate.findOne(query, ApCommentRepay.class);
        //评论不存在
        if (commentRepay==null){
            return ResponseResult.errorResult(AppHttpCodeEnum.DATA_NOT_EXIST,"评论不存在或者已被删除");
        }
        //参数处理
        if (commentRepay.getLikes()==null||commentRepay.getLikes()<0){
            commentRepay.setLikes(0);
        }
        //点赞存入数据表
        Map<String,Object> map=new HashMap<>();
        Update likes=null;
        ApCommentRepayLike apCommentRepayLike=new ApCommentRepayLike();
        apCommentRepayLike.setCommentRepayId(dto.getCommentRepayId());
        apCommentRepayLike.setAuthorId(userId);
        if (dto.getOperation().equals((short)0)){
            mongoTemplate.save(apCommentRepayLike);
            likes = Update.update("likes", commentRepay.getLikes() + 1);
        }else {
            //取消点赞 删除数据
            Query query1 = Query.query(Criteria.where("commentRepayId").is(dto.getCommentRepayId()).and("authorId").is(userId));
            apCommentRepayLike = mongoTemplate.findOne(query1, ApCommentRepayLike.class);
            if (apCommentRepayLike!=null) {
                mongoTemplate.remove(apCommentRepayLike);
                likes = Update.update("likes", commentRepay.getLikes() - 1);
            }
        }
        //修改ApCommentRepay数据的likes;
        mongoTemplate.updateFirst(query,likes,ApCommentRepay.class);
        return ResponseResult.okResult(commentRepay.getLikes());
    }

    /**
     * 自管理的敏感词审核
     * @param content
     * @return
     */
    @Autowired
    private RedisTemplate redisTemplate;

    public boolean handleSensitiveScan(String content) {
        boolean flag = true;
        /*//获取所有的敏感词  -- 先从redis中获取
        List<String> sensitiveList = JSON.parseArray(cacheService.get("Sensitive"),String.class);
        */

        //获取所有的敏感词  -- 先从redis中获取
        List<String> sensitiveList = (List<String>) redisTemplate.opsForValue().get("Sensitive");
        if (sensitiveList == null) {
            List<WmSensitive> wmSensitives = iWemediaClient.list();
            sensitiveList = wmSensitives.stream().map(WmSensitive::getSensitives).collect(Collectors.toList());
            //存入redis中
            cacheService.set("Sensitive",StringUtils.join(sensitiveList,","));
        }

        //初始化敏感词库
        SensitiveWordUtil.initMap(sensitiveList);

        //查看评论中是否包含敏感词
        Map<String, Integer> map = SensitiveWordUtil.matchWords(content);
        if(map.size() >0 ) {
            flag = false;
        }
        return flag;
    }

    /**
     * 审核评论中的纯文本内容
     *
     * @param text
     */
    private boolean scanText(String text) {

        //假设评论能审核通过
        boolean flag = true;

        try {
            //调用百度云API进行内容审核
            Map map = greenScanService.scanText(text);
            //不通过  不能评论
            if ((int) map.get("conclusionType") == WemediaConstants.BAIDU_SCAN_NO_PASS) {
                flag = false;
            }
            //疑似 不能评论
            if ((int) map.get("conclusionType") == WemediaConstants.BAIDU_SCAN_YS) {
                flag = false;
            }
        } catch (Exception e) {
            e.printStackTrace();
        }
        return flag;
    }
}